import java.io.*;
import java.net.*;

/** {@code Player}类 对一位玩家的抽象 */
public class Player {
    /** 连接 */
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    /** 昵称 */
    private String userName;
    /** 资产 */
    private int money;
    /** 两张起脚牌 */
    private Card[] privateCard = new Card[2];
    /** 牌力评分 */
    private long score;
    /** 玩家出局 不参与下一轮游戏 */
    private boolean is出局;
    /** 玩家弃牌 */
    private boolean is弃牌;
    /** 玩家是庄家 */
    private boolean is庄家;
    /** 玩家当前回合投注额 */
    private int playerBets;

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    public void changeMoney(int delta) {
        this.money += delta;
    }

    public long getScore() {
        return score;
    }

    public void setScore(long score) {
        this.score = score;
    }

    public void setIs出局(boolean b) {
        is出局 = b;
    }

    public boolean getIs出局() {
        return is出局;
    }

    public void setIs弃牌(boolean b) {
        is弃牌 = b;
    }

    public boolean getIs弃牌() {
        return is弃牌;
    }

    public void setIs庄家(boolean b) {
        is庄家 = b;
    }

    public boolean getIs庄家() {
        return is庄家;
    }

    /** 获取玩家当前回合投注额 */
    public int getPlayerBets() {
        return playerBets;
    }

    /** 改变玩家当前回合投注额 */
    public void changePlayerBets(int delta) {
        playerBets += delta;
    }

    /** 设置玩家当前回合投注额 */
    public void setPlayerBets(int b) {
        playerBets = b;
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    public Socket getSocket() {
        return socket;
    }

    public void setBufferedReader(BufferedReader in) {
        this.in = in;
    }

    public void setPrintWriter(PrintWriter out) {
        this.out = out;
    }


    public void connect() {
        try {
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public BufferedReader getIn() {
        return in;
    }

    public PrintWriter getOut() {
        return out;
    }

    /** 构造一位玩家 */
    public Player() {
        reset();
    }

    /** 初始化 */
    public void reset() {
        money = 100;
        score = 0;
        is出局 = false;
        is弃牌 = false;
        playerBets = 0;
    }

    /** 获取起脚牌数组 */
    public Card[] getPrivateCard() {
        return privateCard;
    }

    /** @第一回合 玩家摸牌回合 - 玩家从牌堆摸取两张起脚牌 */
    public void turn1(Cards c) throws IOException {
        //connect();
        /* 摸两张起脚牌 */
        privateCard[0] = c.getCard();
        privateCard[1] = c.getCard();
        /* 计算牌力 */
        score = Rule.getScore(this);
        // this.out.println("你的牌:\t" + privateCard[0].toString() + '\t' +
        // privateCard[1].toString());

        // 告知起脚牌
        this.out.println("起脚牌");
        this.out.flush();
        if (!in.readLine().equals("received")) {
            throw new IOException(this.socket + "客户端未响应");
        }
        this.out.println(privateCard[0].getValue());
        this.out.flush();
        if (!in.readLine().equals("received")) {
            throw new IOException(this.socket + "客户端未响应");
        }
        this.out.println(privateCard[1].getValue());
        this.out.flush();
        if (!in.readLine().equals("received")) {
            throw new IOException(this.socket + "客户端未响应");
        }
        // 告知玩家金额
        this.out.println("玩家金额");
        this.out.flush();
        if (!in.readLine().equals("received")) {
            throw new IOException(this.socket + "客户端未响应");
        }
        for (int i = 0; i < 4; i++) {
            this.out.println(Game.currentPlayer().getMoney());
            this.out.flush();
            if (!in.readLine().equals("received")) {
                throw new IOException(this.socket + "客户端未响应");
            }
            Game.toNextPlayer();
        }
        // 告知玩家昵称及身份
        this.out.println("玩家昵称及身份");
        this.out.flush();
        if (!in.readLine().equals("received")) {
            throw new IOException(this.socket + "客户端未响应");
        }
        for (int i = 0; i < 4; i++) {
            this.out.println(Game.currentPlayer().getUserName());
            this.out.flush();
            if (!in.readLine().equals("received")) {
                throw new IOException(this.socket + "客户端未响应");
            }
            this.out.println(Game.currentPlayer().getIs庄家());
            this.out.flush();
            if (!in.readLine().equals("received")) {
                throw new IOException(this.socket + "客户端未响应");
            }
            Game.toNextPlayer();
        }
    }

    /** 进行该玩家的押注回合 */
    public void turn() throws IOException {
        // 告知玩家回合开始
        if (Game.getCurrentRoundBets() - playerBets >= money) {
            this.out.println("<your turn2>");
        } else {
            this.out.println("<your turn3>");
        }
        this.out.flush();
        if (!in.readLine().equals("received")) {
            throw new IOException(this.socket + "客户端未响应");
        }

        int currentRoundBets = Game.getCurrentRoundBets();
        if (playerBets <= currentRoundBets) {
            System.out.println("请选择: 弃牌、跟注(过牌)、加注");

            String s = null;
            while (s == null) {
                try {
                    s = this.in.readLine();
                } catch (Exception e) {
                    s = null;
                }
            }
            int choice = Integer.parseInt(s);

            switch (choice) {
                case 1:
                    this.is弃牌 = true;
                    break;
                case 2:
                    int delta = currentRoundBets - playerBets;
                    if (delta > money) {
                        System.out.println("全押");
                        playerBets = Integer.MAX_VALUE;// 全押整局游戏不再需要投注
                        Game.changePrizePoolAmount(money);
                        money = 0;
                    } else {
                        playerBets = currentRoundBets;
                        Game.changePrizePoolAmount(delta);
                        money -= delta;
                    }
                    break;
                case 3:
                    int add;// 加注额
                    int needToBets;// 当前回合需要补投的注数
                    do {
                        System.out.print("请输入加注数额: ");

                        String input = null;
                        while (input == null) {
                            try {
                                input = this.in.readLine();
                            } catch (Exception e) {
                                input = null;
                            }
                        }
                        add = Integer.parseInt(input);

                        // add = Test.keyin.nextInt();
                        needToBets = currentRoundBets + add - playerBets;// 当前回合应投注额 + 加注额 - 已投注额
                    } while (needToBets > money || add <= 0);
                    Game.changePrizePoolAmount(needToBets);// 补投的注进入奖池
                    money -= needToBets;// 扣除金钱
                    playerBets = currentRoundBets + add;// 更新该玩家当前回合已投注额
                    Game.setCurrentRoundBets(playerBets);// 更新全局当前回合应投注额
                    break;
                default:
                    throw new IllegalArgumentException("非法输入!");
            }
        } else if (playerBets == Integer.MAX_VALUE) {
            System.out.println("该玩家已全押");
        } else {
            throw new IllegalArgumentException(this.toString() + "押注数量异常. playerBets = " + playerBets
                    + ". currentRoundBets = " + currentRoundBets);
        }
    }
}
